#ifndef MEASURE616EDGEDETECT_H
#define MEASURE616EDGEDETECT_H

#include <opencv2/opencv.hpp>
#include <cmath>
#include <ctime>
#define PI 3.1415926

using namespace std;

//#ifndef MEASUR_E616_DRAW_IMG
//#define MEASUR_E616_DRAW_IMG
//#endif

//基准说明：  所有的back setup1  GetDatum616基准
//所有的front 都用setup2基准 但除了SE2front图 只有它用setup1基准
//side用side1的基准setup4
class MeasurE616EdgeDetect
{
public:
    MeasurE616EdgeDetect();
    //求基准 不用
    enum ScanDirection {
        SCAN_DIRECTION_UP      = 1,              // from down to up
        SCAN_DIRECTION_LEFT    = 4,
        SCAN_DIRECTION_DOWN    = 3,
        SCAN_DIRECTION_RIGHT   = 2,
    };
    int GetNewDatum575(cv::Mat srcimg, vector<cv::Point2f>& datum);
	
	
	// back图  SE9  \paras616\back\SE.xml的最后一行 setup1   注意vector<cv::Point2f>& datum要转换到全局图像坐标系下
    int GetDatum616(cv::Mat srcimg, const vector<int> paras,vector<cv::Point2f>& datum);   
	// SE11，SE12的结果contours按顺序输入GetSideDatum616  setup4
    int GetSideDatum616(vector<cv::Point> contour1,vector<cv::Point> contour2,vector<cv::Point2f>& datum);
	
	//SE4和SE7结果输出输入到 FindDatumPoint函数获得基准 setup2
    int FindDatumPoint(vector<cv::Point2f> xpts, vector<cv::Point2f> ypts, vector<cv::Point2f>& datumpts);
    //矩形边缘提取   //RC back图 \paras616\back\RC.xml ；   SE8模板图像的front图  \paras616\front\SE.xml的第8行
    int NewGetRectEdge(cv::Mat srcimg, const vector<int> paras, vector<float>& dists, vector<vector<cv::Point2f>>& contourres);
	
	//side1 图   SE11，SE12  paras616\side1\SE.xml(SE11,SE12 (setup4)分别对应第一行和第二行)
    int GetLineContours(cv::Mat srcimg, const vector<int> paras, vector<cv::Point>& contours);
    //外边缘提取,返回点位  front 图   \paras616\front\S.xml  S.ml的前两行对应S1  后两行S2;     SE1~SE6对应\paras616\front\SE.xml的前6行；SE4 high图  paras616\high\SE.xml 第一行
    int NewKirschEdgeOuter(cv::Mat srcimg, const vector<int> paras, vector<cv::Point2f>& dist);
    //背光图小半圆边缘提取  // CDL back图    \paras616\back\ cdL.xml	
    int NewCircleEdge(cv::Mat srcimg, const vector<int> paras, vector<cv::Point>& contours);
    //螺纹孔边缘提取，返回圆参数
    int NewSmallCircle(cv::Mat srcimg, const vector<int> paras,  vector<float>& result);
    //LD部分边缘提取，返回点位   //SE1~SE5 back图  \paras616\back\SE.xml 前五行；   SE2front图 （setup1）  \paras616\front\SE.xml的第9行；SE7 high图  paras616\high\SE.xml 第2行；side 图    SE10(FAI37) paras616\side\SE.xml               
    int LDmeasure(cv::Mat srcimg, const vector<int> paras, vector<cv::Point2f>& respts);
    //新螺纹孔边缘提取，返回圆参数  SE8模板图像的front图     \paras616\front\SE.xml的第7行    
    int SmallCircle(cv::Mat srcimg, const vector<int> paras, vector<float>& res, int flag);

    float GetParallelism(vector<cv::Point2f> contour,int flag);
    float GetLineDist(vector<cv::Point2f> contour1,vector<cv::Point2f> contour2,int flag);
    float GetRoundness(vector<cv::Point> contour, cv::Point2f center);
    float GetPosition(cv::Point2f stdposition,cv::Point2f measurepos);
    float GetLine2LineMid(vector<cv::Point2f> contour1,vector<cv::Point2f> contour2,int flag);
    vector<float> FitCircle(vector<cv::Point>& contours);
    void LineFitLeastSquaresf(vector<cv::Point2f> contours, vector<float> &vResult);

    int LDmeasurerevise(cv::Mat srcimg, const vector<int> paras, vector<cv::Point2f>& respts);

private:
    int ScanLineRange(cv::Mat srcimg,int lineori, vector<cv::Point>& contours,int startline,int startedge, int endedge, int radius,float percent);
    float PointLineDist(cv::Point2f A,vector<float> Lineparas);

    void LineFitLeastSquares(vector<cv::Point> contours, vector<float> &vResult);
    //用中心点加旋转射线方法找边缘
    int FindEdge(cv::Mat srcimg, cv::Point seed, vector<cv::Point>& contours, int radius, float percent, int radthresh);
    //已知方向，通过从一边线扫求边缘
    int ScanLine(cv::Mat srcimg,int lineori, vector<cv::Point>& contours,int startline,int radius,float percent);
    //判断点周围密度
    int PointDense(cv::Mat srcimg, cv::Point center, int rad, float thresh);
    //krisch边缘检测
    cv::Mat krisch(cv::InputArray src,int borderType = cv::BORDER_DEFAULT);
    //卷积
    void conv2D(cv::InputArray _src, cv::InputArray _kernel, cv::OutputArray _dst, int ddepth, cv::Point anchor = cv::Point(-1, -1), int borderType = cv::BORDER_DEFAULT);
    //找到边缘检测起始位置,单次边缘
    void GetSeedPoints(cv::Mat srcimg,int offset, int orientation,int startline,int endline,int threshold, vector<cv::Point>& seedpoints);
    //获取图像边缘点,根据像素值无阈值分割
    void GetSrcEdgePoints(cv::Mat srcimg,int offset0,int orientation,int offset,int startline,int endline,int threshold, int threshold1, vector<cv::Point>& edgepoints);
    //获取图像边缘点
    void GetEdgePoint(cv::Mat srcimg, vector<cv::Point> seedpoints, int orientation, int thresh,int radius,float percent, vector<cv::Point>& contours);
    //找到边缘检测起始位置,两次边缘
    void GetSeedPointsSec(cv::Mat srcimg,int offset,int orientation,int startline,int endline,int threshold, vector<cv::Point>& seedpoints);
    //以2*2矩阵求均值生成像素变化曲线
    int Pixel2Curve(cv::Mat srcimg,int startpos, int endpos, int orientation, vector<vector<float>>& curves);
    //找到边缘检测起始位置,单次边缘
    void GetSeedPos(vector<vector<float>> curves,int offset,int thresh, vector<int>& seedpoints);
    //找到边缘检测起始位置,两次边缘
    void GetSeedPosSecond(vector<vector<float>> curves,int offset,int thresh, vector<int>& seedpoints);

    vector<cv::Point> ContoursCut(vector<cv::Point> contours,int startangle,int endangle);


    template<typename T1,typename T2>
    float Point2Point(T1 A,T2 B);
};

#endif // MEASURE616EDGEDETECT_H
